package edu.calvin.djs32.cs214.interpreters.frontend;

import static org.norecess.antlr.Assert.assertToken;

import org.junit.Before;
import org.junit.Test;
import org.norecess.antlr.ANTLRTester;

import edu.calvin.djs32.cs214.interpreters.frontend.Hobbes2008FrontEnd;
import edu.calvin.djs32.cs214.interpreters.frontend.Hobbes2008Lexer;

public class Hobbes2008LexerTest {

	private ANTLRTester _tester;

	@Before
	public void setUp() {
		_tester = new ANTLRTester(new Hobbes2008FrontEnd());
	}
	
	@Test
	public void shouldRecognizeIntegers() {
		assertToken(Hobbes2008Lexer.INTEGER, "1", _tester.scanInput("1"));
		assertToken(Hobbes2008Lexer.INTEGER, "4", _tester.scanInput("4"));
		assertToken(Hobbes2008Lexer.INTEGER, "9", _tester.scanInput("9"));
		assertToken(Hobbes2008Lexer.INTEGER, "12", _tester.scanInput("12"));
		assertToken(Hobbes2008Lexer.INTEGER, "123", _tester.scanInput("123"));
	}
	
	@Test
	public void shouldRecognizeNegativeIntegers(){
		assertToken(Hobbes2008Lexer.INTEGER, "-123", _tester.scanInput("-123"));
		assertToken(Hobbes2008Lexer.INTEGER, "-4568", _tester.scanInput("-4568"));
	}
	
	@Test
	public void shouldRecognizePositiveIntegers() {
		assertToken(Hobbes2008Lexer.INTEGER, "+123", _tester.scanInput("+123"));
	}
	
	@Test
	public void shouldRecognizeHexadecimalIntegers() {
		assertToken(Hobbes2008Lexer.INTEGER, "0x123f", _tester.scanInput("0x123f"));
	}
	
	@Test
	public void shouldRecognizeNegativeHexadecimalIntegers(){
		assertToken(Hobbes2008Lexer.INTEGER, "-0x123f", _tester.scanInput("-0x123f"));		
	}
	
	@Test
	public void shouldRecognizePositiveHexadecimalIntegers(){
		assertToken(Hobbes2008Lexer.INTEGER, "+0x123f", _tester.scanInput("+0x123f"));
	}
	
	@Test
	public void shouldIgnoreWhitespace() {
	  assertToken(Hobbes2008Lexer.INTEGER, "1", _tester.scanInput("1 "));
	  assertToken(Hobbes2008Lexer.INTEGER, "4", _tester.scanInput(" 4"));
	  assertToken(Hobbes2008Lexer.INTEGER, "123", _tester.scanInput("  123"));
	  assertToken(Hobbes2008Lexer.INTEGER, "9", _tester.scanInput("  9"));
	  assertToken(Hobbes2008Lexer.INTEGER, "8", _tester.scanInput(" 8 "));
	  assertToken(Hobbes2008Lexer.INTEGER, "8", _tester.scanInput("\t8"));               
	  assertToken(Hobbes2008Lexer.INTEGER, "8", _tester.scanInput("\n8"));         
	  assertToken(Hobbes2008Lexer.INTEGER, "8", _tester.scanInput(" \t\n8 "));
	}
	
	@Test
	public void shouldIgnoreBlockComments() {
	  assertToken(Hobbes2008Lexer.INTEGER, "1", _tester.scanInput("/* fweafea */ \n 1"));
	  assertToken(Hobbes2008Lexer.INTEGER, "0x123f", _tester.scanInput("/* fweafea */ \n 0x123f"));
	}
	
	@Test
	public void shouldIgnoreEOLComments() {
	  assertToken(Hobbes2008Lexer.INTEGER, "1", _tester.scanInput("1 //do this work \n"));
	  assertToken(Hobbes2008Lexer.INTEGER, "0x123f", _tester.scanInput("0x123f //do this work \n"));
	}
	
	@Test
	public void shouldRecognizeStrings() {
		assertToken(Hobbes2008Lexer.STRING, "'foo'", _tester.scanInput("'foo'"));
		assertToken(Hobbes2008Lexer.STRING, "'foo bar'", _tester.scanInput("'foo bar'"));
		assertToken(Hobbes2008Lexer.STRING, "' '", _tester.scanInput("' '"));
	}
	
	@Test
	public void shouldRecognizePunctuation() {
	  assertToken(Hobbes2008Lexer.COMMA, ",", _tester.scanInput(","));
	  assertToken(Hobbes2008Lexer.LPAREN, "(", _tester.scanInput("("));
	  assertToken(Hobbes2008Lexer.RPAREN, ")", _tester.scanInput(")"));
	}
	
	@Test
	public void shouldRecognizeIdentifiers(){
		assertToken(Hobbes2008Lexer.IDENTIFIER, "*", _tester.scanInput("*"));
		assertToken(Hobbes2008Lexer.IDENTIFIER, "+", _tester.scanInput("+"));
		assertToken(Hobbes2008Lexer.IDENTIFIER, "-", _tester.scanInput("-"));
		assertToken(Hobbes2008Lexer.IDENTIFIER, "/", _tester.scanInput("/"));
		assertToken(Hobbes2008Lexer.IDENTIFIER, "!", _tester.scanInput("!"));
		assertToken(Hobbes2008Lexer.IDENTIFIER, "abs", _tester.scanInput("abs"));
		assertToken(Hobbes2008Lexer.IDENTIFIER, "<", _tester.scanInput("<"));
		assertToken(Hobbes2008Lexer.IDENTIFIER, "<=", _tester.scanInput("<="));
		assertToken(Hobbes2008Lexer.IDENTIFIER, "=", _tester.scanInput("="));
		assertToken(Hobbes2008Lexer.IDENTIFIER, "!=", _tester.scanInput("!="));
		assertToken(Hobbes2008Lexer.IDENTIFIER, ">", _tester.scanInput(">"));
		assertToken(Hobbes2008Lexer.IDENTIFIER, ">=", _tester.scanInput(">="));
	}
	
	@Test
	public void shouldRecognizeKeywords(){
		assertToken(Hobbes2008Lexer.IF, "if", _tester.scanInput("if"));
		assertToken(Hobbes2008Lexer.ELSE, "else", _tester.scanInput("else"));
		assertToken(Hobbes2008Lexer.THEN, "then", _tester.scanInput("then"));
		assertToken(Hobbes2008Lexer.END, "end", _tester.scanInput("end"));
	}
}